package com.example;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

import static com.example.CollectorsAction.menu;
/**
 * @author Liuqz
 * @date 2018/11/18 19:58
 */
public class CollectorsAction3 {


    public static void main(String[] args) {
        testPartitioningByWithPredicate();
        testPartitioningByWithPredicateAndCollector();
        testReducingBinaryOperator();
        testReducingBinaryOperatorAndIdentiy();
        testReducingBinaryOperatorAndIdentiyAndFunction();
        testSummarizingDouble();
        testSummarizingLong();
        testSummarizingInt();
    }

    /**
     * partitioningBy(Predicate<? super T> predicate)
     * result : {false=[Dish(name=pork, vegetarian=false, calories=800, type=MEAT), Dish(name=beef, vegetarian=false, calories=700, type=MEAT), Dish(name=chicken, vegetarian=false, calories=400, type=MEAT), Dish(name=prawns, vegetarian=false, calories=300, type=FISH), Dish(name=salmon, vegetarian=false, calories=450, type=FISH)], true=[Dish(name=french fries, vegetarian=true, calories=530, type=OTHER), Dish(name=rice, vegetarian=true, calories=350, type=OTHER), Dish(name=season fruit, vegetarian=true, calories=120, type=OTHER), Dish(name=pizza, vegetarian=true, calories=550, type=OTHER)]}
     */
    private static void testPartitioningByWithPredicate() {
        System.out.println("testPartitioningByWithPredicate");
        Map<Boolean, List<Dish>> map = menu.stream().collect(Collectors.partitioningBy(Dish::isVegetarian));
        Optional.ofNullable(map).ifPresent(System.out::println);
    }

    /**
     * partitioningBy(Predicate<? super T> predicate,Collector<? super T, A, D> downstream)
     * result : {false=530.0, true=387.5}
     */
    private static void testPartitioningByWithPredicateAndCollector() {
        System.out.println("testPartitioningByWithPredicateAndCollector");
        Optional.ofNullable(menu.stream().collect(Collectors.partitioningBy(Dish::isVegetarian, Collectors.averagingInt(Dish::getCalories)))).ifPresent(System.out::println);
    }

    /**
     * result : Optional[Dish(name=pork, vegetarian=false, calories=800, type=MEAT)]
     */
    private static void testReducingBinaryOperator() {
        System.out.println("testReducingBinaryOperator");
        Optional.ofNullable(menu.stream().collect(Collectors.reducing(BinaryOperator.maxBy(Comparator.comparingInt(Dish::getCalories))))).ifPresent(System.out::println);
    }

    /**
     * 计算所有的Dish.Calories总和
     * result : 4200
     */
    private static void testReducingBinaryOperatorAndIdentiy() {
        System.out.println("testReducingBinaryOperatorAndIdentiy");
        Optional.ofNullable(menu.stream().map(Dish::getCalories).collect(Collectors.reducing(0,((d1,d2) -> d1 + d2)))).ifPresent(System.out::println);
    }

    /**
     * 计算所有的Dish.Calories总和
     * result : 4200
     */
    private static void testReducingBinaryOperatorAndIdentiyAndFunction() {
        System.out.println("testReducingBinaryOperatorAndIdentiyAndFunction");
        Optional.ofNullable(menu.stream().collect(Collectors.reducing(0, Dish::getCalories, (d1, d2) -> d1 + d2))).ifPresent(System.out::println);
    }

    /**
     * result : DoubleSummaryStatistics{count=9, sum=4200.000000, min=120.000000, average=466.666667, max=800.000000}
     */
    private static void testSummarizingDouble() {
        System.out.println("testSummarizingDouble");
        Optional.of(menu.stream().collect(Collectors.summarizingDouble(Dish::getCalories)))
                .ifPresent(System.out::println);
    }

    /**
     * result : LongSummaryStatistics{count=9, sum=4200, min=120, average=466.666667, max=800}
     */
    private static void testSummarizingLong() {
        System.out.println("testSummarizingLong");
        Optional.of(menu.stream().collect(Collectors.summarizingLong(Dish::getCalories)))
                .ifPresent(System.out::println);
    }

    /**
     * result : IntSummaryStatistics{count=9, sum=4200, min=120, average=466.666667, max=800}
     */
    private static void testSummarizingInt() {
        System.out.println("testSummarizingLong");
        Optional.of(menu.stream().collect(Collectors.summarizingInt(Dish::getCalories)))
                .ifPresent(System.out::println);
    }

}
